using System;
using System.Net;
using System.Threading;
using Kugar.Core.ExtMethod;

namespace Kugar.Core.Communications.Transfer
{
    public class RUDPConnectionInternal : INetTransfer
    {
        private int _connectID;
        private RUDPConnection _rUDPLink;

        internal RUDPConnectionInternal(int connectId, RUDPConnection rUdpLink)
        {
            _connectID = connectId;
            _rUDPLink = rUdpLink;

            _rUDPLink.AfterDataSended += OnAfterSendData;
        }

        public Guid TransferID
        {
            get { throw new NotImplementedException(); }
        }

        //public int Send(byte[] sendStruct)
        //{
        //    return Send(sendStruct, 0, sendStruct.Length);
        //}

        //public int Send(byte[] sendStruct, int offset, int count)
        //{
        //    var sc = 0;
        //    IAsyncResult iar = null;
        //    iar = BeginSend(sendStruct, offset, count, (o) =>
        //                                               {
        //                                                   sc = EndSend(o);
                                                               
        //                                               }, null);

        //    iar.AsyncWaitHandle.WaitOne(30000, false);

        //    return sc;
        //}

        //public IAsyncResult BeginSend(byte[] data, AsyncCallback callback, object state)
        //{
        //    return BeginSend(data, 0, data.Length, callback, state);
        //}

        //public IAsyncResult BeginSend(byte[] data, int offset, int count, AsyncCallback callback, object state)
        //{
        //    return _rUDPLink.BeginSend(data, offset, count, callback, state);
        //}

        //public int EndSend(IAsyncResult iar)
        //{
        //    return _rUDPLink.EndSend(iar);
        //}

        //public int EndSend(IAsyncResult iar, ref Exception error)
        //{
        //    return _rUDPLink.EndSend(iar,ref error);
        //}

        public bool SendAsync(TransferAsyncEventArgs e)
        {
           return  _rUDPLink.SendAsync(e);
        }

        public bool ReceiveAsync(TransferAsyncEventArgs e)
        {
            return _rUDPLink.ReceiveAsync(e);
        }

        //public IAsyncResult BeginReceive(byte[] buffer, AsyncCallback callback, object state)
        //{
        //    return BeginReceive(buffer, 0, buffer.Length, callback, state);
        //}

        //public IAsyncResult BeginReceive(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        //{
        //    return _rUDPLink.BeginReceive(buffer,offset, count, callback, state);
        //}

        //public int EndReceive(IAsyncResult iar)
        //{
        //    Exception error = null;

        //    var c= EndReceive(iar, ref error);

        //    if (error!=null)
        //    {
        //        throw error;
        //    }
        //    else
        //    {
        //        return c;
        //    }
        //}

        //public int EndReceive(IAsyncResult iar, ref Exception error)
        //{
        //    return _rUDPLink.EndReceive(iar, ref error);
        //}

        public int ConnectID
        {
            get { return _connectID; }
        }

        public void Start()
        {
            _rUDPLink.Start();
        }

        public void Stop()
        {
            _rUDPLink.Stop();
        }

        public void Close()
        {
           // _rUDPLink.Close();
           _rUDPLink.OnBeginClosing();
        }

        public bool IsStop
        {
            get { return _rUDPLink.Status == RUDPConnectStatus.Stop; }
        }

        public int ReceiveBufferCount
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public bool IsActivity
        {
            get { return _rUDPLink.Status == RUDPConnectStatus.ESTABLISHED || _rUDPLink.Status== RUDPConnectStatus.Stop; }
        }

        public event EventHandler<TransferAsyncEventArgs> BeforceSendData;
        public event EventHandler<TransferAsyncEventArgs> AfterSendData;
        public event EventHandler<TransferAsyncEventArgs> AfterReceiveData;
        public event EventHandler<TransferClosedEventArgs> TransferClosed;
        public event EventHandler TransferStop;
        public event EventHandler TransferStart;

        //public event EventHandler<RUDPDisconnectedEventArgs> Disconnected;

        internal void OnReceiveData(TransferAsyncEventArgs e)
        {
            Events.EventHelper.RaiseAsync(AfterReceiveData, this, e);
        }

        internal void OnDisconnected(RUDPDisconnectedEventArgs e)
        {

            Events.EventHelper.Raise(TransferClosed, this, new TransferClosedEventArgs(this));


            TransferClosed=null;

        }

        internal void OnBeforceSendData(TransferAsyncEventArgs e)
        {
            Events.EventHelper.Raise(BeforceSendData,this,e);
        }

        internal void OnAfterSendData(object sender, TransferAsyncEventArgs e)
        {
            if (AfterReceiveData!=null)
            {
                ThreadPool.QueueUserWorkItem((o) =>
                                                 {
                                                     AfterSendData(this, (TransferAsyncEventArgs) o);
                                                 }, e);
            }

            //Events.EventHelper.Raise(AfterSendData, this, e);
        }

        #region Implementation of IDisposable

        public void Dispose()
        {
            this.Close();

            BeforceSendData=null;
            AfterSendData=null;
            AfterReceiveData=null;
            TransferStart=null;
            TransferStop=null;

        }

        #endregion

        #region Implementation of INetTransfer

        public int LocalPort
        {
            get { return _rUDPLink.LocalPort; }
        }

        public IPEndPoint RemotePoint
        {
            get { return _rUDPLink.RemotePoint; }
        }

        #endregion
    }
}